package com.ruoyi.common.utils;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.nio.file.*;
import java.time.Duration;
import java.time.Instant;
import java.util.Random;

/**
 * 图片过度曝光处理器
 * 功能：
 * 1. 递归遍历目录及其子目录
 * 2. 处理常见图片格式（JPG/PNG/GIF）
 * 3. 应用随机强度过度曝光效果
 * 4. 保持目录结构输出处理结果
 */
public class ImageExposureProcessor {

    // 主入口方法
    public static void main(String[] args) {
        System.out.println("[INFO] 程序启动");
        Path inputDir = Paths.get("C:\\Users\\lenovo\\Desktop\\0-异常数据原图");
        Path outputDir = Paths.get("C:\\Users\\lenovo\\Desktop\\异常数据原图\\过亮");

        Instant start = Instant.now();
        processImages(inputDir, outputDir);
        Duration duration = Duration.between(start, Instant.now());

        System.out.printf("[SUCCESS] 处理完成! 总耗时: %d分 %d秒%n",
                duration.toMinutesPart(), duration.toSecondsPart());
    }

    /**
     * 核心处理方法
     * @param inputDir  输入目录路径
     * @param outputDir 输出目录路径
     */
    public static void processImages(Path inputDir, Path outputDir) {
        try {
            System.out.printf("[INFO] 开始处理目录: %s%n", inputDir.toAbsolutePath());

            Files.walk(inputDir)
                    .filter(Files::isRegularFile)
                    .forEach(path -> {
                        try {
                            if (isImageFile(path)) {
                                System.out.printf("[PROCESS] 开始处理: %s%n", path);
                                Instant fileStart = Instant.now();

                                BufferedImage original = ImageIO.read(path.toFile());
                                float exposure = generateExposureValue(2f, 4.0f);
                                System.out.printf("[PARAM] 曝光强度: %.2f倍%n", exposure);

                                BufferedImage processed = applyExposure(original, exposure);

                                // 传递exposure参数到保存方法
                                saveImage(processed, inputDir, outputDir, path, exposure);

                                Duration fileDuration = Duration.between(fileStart, Instant.now());
                                System.out.printf("[SUCCESS] 处理完成: %s (耗时: %dms)%n%n",
                                        path, fileDuration.toMillis());
                            }
                        } catch (IOException e) {
                            System.err.printf("[ERROR] 处理失败: %s | 原因: %s%n",
                                    path, e.getMessage());
                        }
                    });
        } catch (IOException e) {
            System.err.printf("[FATAL] 目录遍历错误: %s%n", e.getMessage());
        }
    }

    /**
     * 判断是否为支持的图片文件
     */
    private static boolean isImageFile(Path path) {
        String fileName = path.getFileName().toString().toLowerCase();
        return fileName.endsWith(".jpg") || fileName.endsWith(".jpeg")
                || fileName.endsWith(".png") || fileName.endsWith(".gif");
    }

    /**
     * 生成随机曝光值（含两位小数）
     * @param min 最小值（例如1.5）
     * @param max 最大值（例如3.0）
     */
    private static float generateExposureValue(float min, float max) {
        Random rand = new Random();
        return min + rand.nextFloat() * (max - min);
    }

    /**
     * 应用过度曝光效果
     * @param image 原始图片
     * @param exposure 曝光系数（大于1的值）
     */
    private static BufferedImage applyExposure(BufferedImage image, float exposure) {
        // 转换为标准RGB格式
        BufferedImage converted = convertToRGB(image);
        int width = converted.getWidth();
        int height = converted.getHeight();

        // 创建结果缓冲区
        BufferedImage result = new BufferedImage(width, height, converted.getType());

        // 遍历每个像素
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                // 获取原始像素值
                int pixel = converted.getRGB(x, y);

                // 分解RGB通道
                int r = (pixel >> 16) & 0xFF;
                int g = (pixel >> 8) & 0xFF;
                int b = pixel & 0xFF;

                // 应用曝光计算
                r = Math.min(255, (int)(r * exposure));
                g = Math.min(255, (int)(g * exposure));
                b = Math.min(255, (int)(b * exposure));

                // 重组像素值
                int newPixel = (r << 16) | (g << 8) | b;
                result.setRGB(x, y, newPixel);
            }
        }
        return result;
    }

    /**
     * 转换图片为RGB格式（去除透明通道）
     */
    private static BufferedImage convertToRGB(BufferedImage image) {
        if (image.getType() == BufferedImage.TYPE_INT_RGB) return image;

        BufferedImage newImage = new BufferedImage(
                image.getWidth(),
                image.getHeight(),
                BufferedImage.TYPE_INT_RGB);
        newImage.createGraphics().drawImage(image, 0, 0, null);
        return newImage;
    }

    /**
     * 保存处理后的图片
     */
    private static void saveImage(BufferedImage image, Path inputDir, Path outputDir,
                                  Path filePath, float exposure) {
        try {
            // 原文件名处理
            String originalName = filePath.getFileName().toString();
            int dotIndex = originalName.lastIndexOf('.');

            // 分割文件名和扩展名
            String baseName = (dotIndex == -1) ? originalName : originalName.substring(0, dotIndex);
            String extension = (dotIndex == -1) ? "" : originalName.substring(dotIndex);

            // 构建新文件名（格式：原名称_系数.扩展名）
            String newFileName = String.format("%s_%.2f%s", baseName, exposure, extension);

            // 保持目录结构
            Path relativePath = inputDir.relativize(filePath).getParent();
            Path outputPath = outputDir.resolve(relativePath == null ? null : relativePath);
            outputPath = outputPath.resolve(newFileName);

            Files.createDirectories(outputPath.getParent());
            String format = getFormatName(originalName);
            ImageIO.write(image, format, outputPath.toFile());
            System.out.printf("[OUTPUT] 保存至: %s%n", outputPath);
        } catch (IOException e) {
            System.err.printf("[SAVE_ERROR] 保存失败: %s | 原因: %s%n",
                    filePath, e.getMessage());
            throw new RuntimeException(e);
        }
    }

    /**
     * 根据扩展名获取图片格式
     */
    private static String getFormatName(String fileName) {
        String lowerName = fileName.toLowerCase();
        if (lowerName.endsWith(".png")) return "PNG";
        if (lowerName.endsWith(".gif")) return "GIF";
        return "JPEG"; // 默认使用JPEG格式
    }
}
